//
// Created by 邹嘉旭 on 2025/8/5.
//
#include "elements/elements.h"

#include "as_entity.h"
#include "services/dashboard.h"
#include "util/log.h"

static void *element_conn_connect(net_ctx_t *ctx, char *remote_addr, int remote_port, int local_port) {

    element_propt_t *element_propt = malloc(sizeof(element_propt_t));

    element_propt->bc.remote_addr = strdup(remote_addr);
    element_propt->bc.remote_port = remote_port;
    element_propt->bc.local_port = local_port;


    if (init_basic_conn_client(&element_propt->bc, ctx, LD_TCPV6_CLIENT) == FALSE) {
        return NULL;
    }

    // 只有当成功连接时
    client_interface_t *client_interface = ctx->arg;
    element_propt->peer_sac = client_interface->peer_SAC;
    element_propt->interface_type = client_interface->meta.interface_type;
    list_add_tail(&element_propt->lpointer, client_interface->meta.net_ele->propt_head);

    return element_propt;
}

static l_err element_conn_accept(net_ctx_t *ctx, int fd, struct sockaddr_storage *saddr) {
    element_propt_t *element_propt = malloc(sizeof(element_propt_t));

    if (init_basic_conn_server(&element_propt->bc, ctx, LD_TCPV6_SERVER, fd, saddr) == FALSE) {
        log_error("Cannot initialize connection!");
        free(element_propt);
        return LD_ERR_INTERNAL;
    }

    uint16_t client_port = get_port(&element_propt->bc);
    server_interface_t *server_interface = ctx->arg;

    FOREACH_PEERS(server_interface,  {
                  if (client_port == peer->peer_port) {

                      peer->is_connect = TRUE;
                      element_propt->peer_sac = peer->peer_SAC;
                      element_propt->interface_type = server_interface->meta.interface_type;

                  list_add_tail(&element_propt->lpointer, server_interface->meta.net_ele->propt_head);
                  return LD_OK;
                  }
});

    cn_log_error( server_interface->meta.net_ele->element_tag, server_interface->meta.interface_type, "No available connection from port `%d`!", client_port);
    return LD_ERR_INTERNAL;
}

static void element_conn_close(basic_conn_t *bc) {
    element_propt_t *element_propt = (element_propt_t *) bc;
    if (!element_propt) return;

    net_ctx_t *ctx = bc->opt;
    meta_service_t *meta = ctx->arg;
    if (meta->is_client) {
        client_interface_t *cli = (client_interface_t *)meta;
        free(cli->propt);
        cli->propt = NULL;
    }else {
        server_interface_t *ser = (server_interface_t *)meta;
        uint16_t client_port = get_port(&element_propt->bc);
        // delete_peer_enode_by_peerptr(ser->eles_map, element_propt, NULL);
        FOREACH_PEERS(ser, {
            if (client_port == peer->peer_port) {
                peer->is_connect = FALSE;
            break;
            }
        });
    }

    free(element_propt);
    log_error("Closing connection!");
}

/**
 * 设置当前接口的元服务
 * @param meta 元服务
 * @param net_ele
 * @param is_client 是否为客户端
 * @return
 */
static l_err set_meta(meta_service_t *meta, net_element_t *net_ele, bool is_client, l_err (*recv_handler)(basic_conn_t *)) {

    if (!meta) {
        cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "meta is null");
        return LD_ERR_NULL;
    }

    memcpy(meta->ctx.name, "AAAAA", 5);
    meta->ctx.conn_handler = element_conn_connect;
    meta->ctx.accept_handler = element_conn_accept;
    meta->ctx.recv_handler = recv_handler;
    meta->ctx.send_handler = defalut_send_pkt;
    meta->ctx.close_handler = element_conn_close;
    meta->ctx.epoll_fd = core_epoll_create(0, -1);
    meta->ctx.arg = meta;
    meta->net_ele = net_ele;
    meta->is_client = is_client;
    
    return LD_OK;
}

/**
 * 根据配置启动当前网元的socket服务
 * @param net_ele 网元
 * @param server_handler 服务端角色业务
 * @param client_handler 客户端角色业务
 * @return
 */
l_err init_element_service(net_element_t *net_ele, recv_handler server_handler, recv_handler client_handler) {
    zero(net_ele->meta_map);

    net_ele->propt_head = &net_ele->propts.lpointer;
    init_list_head(net_ele->propt_head);


    switch (net_ele->element_type) {
        case ELEMENT_DBSM:
        case ELEMENT_RDF:
            net_ele->as_map = init_as_senode_map();
            break;
        case ELEMENT_AMM:
        case ELEMENT_GSG:
            net_ele->as_map = init_as_uenode_map();
            break;
        default:
            cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "Unhandled element type");
            break;
    }

    // 按服务端接口配置逐一启动service
    for (size_t i = 0; i < net_ele->server_interface_count; i++) {
        server_interface_t *intf = &net_ele->server_interfaces[i];
        init_heap_desc(&intf->meta.ctx.hd_conns);
        if (set_meta(&intf->meta, net_ele, FALSE, server_handler) != LD_OK) {
            cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "Meta set failed");
            return LD_ERR_INTERNAL;
        }

        // if ((intf->eles_map = init_element_enode_map()) == NULL) {
        //     cn_log_error(net_ele->element_tag, intf->meta.interface_type ,"Cannot initialize meta services!");
        //     return LD_ERR_NULL;
        // }
        net_ele->meta_map[intf->meta.interface_type] = &intf->meta;

        server_entity_setup(intf->local_port, &intf->meta.ctx, LD_TCPV6_SERVER );

        pthread_create(&intf->meta.th, NULL, net_setup, &intf->meta.ctx);
        pthread_detach(intf->meta.th);
    }

    // 按客户端接口配置逐一启动service
    for (size_t i = 0; i < net_ele->client_interface_count; i++) {
        client_interface_t *intf = &net_ele->client_interfaces[i];
        if (set_meta(&intf->meta, net_ele,TRUE, client_handler) != LD_OK) {
            return LD_ERR_INTERNAL;
        }

        net_ele->meta_map[intf->meta.interface_type] = &intf->meta;

        intf->propt = client_entity_setup(&intf->meta.ctx, intf->peer_addr_v6, intf->peer_port, intf->local_port);
        pthread_create(&intf->meta.th, NULL, net_setup, &intf->meta.ctx);
        pthread_detach(intf->meta.th);
    }

    if (is_dashboard) {
        init_dashboard(&net_ele->dashboard_obj, dashboard_data_recv);
        handle_register_cn_dashboard(&net_ele->dashboard_obj, net_ele->element_type, net_ele->SAC);
    }

    return LD_OK;
}

l_err destroy_element_service(net_element_t *net_ele) {

    for (size_t i = 0; i < INTERFACE_NODE_MAX; i++) {
        //TODO 释放net_ctx的内存
        meta_service_t *meta = net_ele->meta_map[i];
        if (!meta) continue;

        if (meta->is_client) {
            client_interface_t *cli = (client_interface_t *)meta;
        }else {
            server_interface_t *ser = (server_interface_t *)meta;
        }
    }

    if (net_ele->stop_func) {
        net_ele->stop_func(net_ele);
    }else {
        cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "No destory function defined");
    }

    pthread_cancel(net_ele->th);
    return LD_OK;
}

/**
 * 按端口获取连接
 * @param net_ele 网元
 * @param type 接口类型
 * @param peer_SAC 对端端口，如果为0则不指定对端SAC，当发送的一方为服务器角色且有不止一个客户端时，例如G1端口，应唯一地给出对端SAC
 * @return
 */
element_propt_t *get_propt(net_element_t *net_ele, interface_type_t type, uint16_t peer_SAC) {
    struct list_head *pos;
    list_for_each(pos, net_ele->propt_head) {
        element_propt_t *propt = list_entry(pos, element_propt_t, lpointer);
        if (propt->interface_type == type) {
            if (peer_SAC == 0 || peer_SAC == propt->peer_sac){
                return propt;
            }
        }
    }
    return NULL;
}
element_propt_t *get_propt_by_ip_port(net_element_t *net_ele, interface_type_t type, char *peer_IP, uint16_t port) {
    struct list_head *pos;
    // list_for_each(pos, net_ele->propt_head) {
    //     element_propt_t *propt = list_entry(pos, element_propt_t, lpointer);
    //     if (propt->interface_type == type) {
    //         struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&propt->bc.saddr;
    //
    //         log_warn("%d %d",port, ntohs(addr->sin6_port));
    //     }
    // }
    list_for_each(pos, net_ele->propt_head) {
        element_propt_t *propt = list_entry(pos, element_propt_t, lpointer);
        if (propt->interface_type == type) {
            if (peer_IP == NULL || port == 0)   return propt;
            struct sockaddr_in6 *addr = (struct sockaddr_in6 *)&propt->bc.saddr;

            if (port == ntohs(addr->sin6_port)) {
                return propt;
            }
        }
    }
    return NULL;
}

client_interface_t *get_client_interface(net_element_t *net_ele, element_type_t type) {
    for (int i = 0; i < net_ele->client_interface_count; i++)
        if (net_ele->client_interfaces[i].meta.interface_type == type) {
            return &net_ele->client_interfaces[i];
        }
    return NULL;
}

net_element_t *get_element_by_tag(element_type_t type, const char *tag) {
    for (int i = 0; i < elements_count; i++) {
        if (type == elements[i].element_type) {
            if (strcmp(tag, elements[i].element_tag) == 0)  return &elements[i];
        }
    }
    return NULL;
}

net_element_t *get_element_by_SAC(uint16_t SAC) {
    for (int i = 0; i < elements_count; i++) {
        if (elements[i].SAC == SAC) {
            return &elements[i];
        }
    }
    return NULL;
}
